home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / others / ole_101.zip / PATRON.ZIP / OLEOBJ.C < prev    next >
C/C++ Source or Header  |  1992-04-13  |  21KB  |  801 lines

  1. /*
  2.  * OLEOBJ.C
  3.  *
  4.  * Constructor and Destructor for the OBJECT structure.  Since this is
  5.  * not a placeholder for a real OLE structure, there is no VTBL and
  6.  * so there are no standard methods for it.
  7.  *
  8.  * Copyright(c) Microsoft Corp. 1992 All Rights Reserved
  9.  *
  10.  */
  11.  
  12. #include <windows.h>
  13. #include <ole.h>
  14. #include "oclient.h"
  15.  
  16.  
  17.  
  18.  
  19. /*
  20.  * PObjectAllocate
  21.  *
  22.  * Purpose:
  23.  *  Allocates an OBJECT structure.  This function only creates the
  24.  *  structure and inserts it into the owner's list.
  25.  *
  26.  * Parameters:
  27.  *  pfSuccess       LPBOOL indicating if the initialization succeeded.  If
  28.  *                  this function returns non-NULL, but *pfSuccess==FALSE,
  29.  *                  the caller must call the destructor function.
  30.  *  pDoc            LPDOCUMENT to the owner of this object, which contains
  31.  *                  pObjLast where we attach ourself, and a pszData1 scratch
  32.  *                  area.
  33.  *
  34.  * Return Value:
  35.  *  LPOBJECT        Pointer to the allocated OBJECT if successful, NULL
  36.  *                  if the allocation failed or a parameter is invalid.
  37.  */
  38.  
  39. LPOBJECT FAR PASCAL PObjectAllocate(LPBOOL pfSuccess, LPDOCUMENT pDoc)
  40.     {
  41.     HANDLE              hMem;
  42.     LPOBJECT            pObj;
  43.  
  44.     if (NULL==pfSuccess)
  45.         return NULL;
  46.  
  47.     *pfSuccess=FALSE;
  48.  
  49.     if (NULL==pDoc)
  50.         return NULL;
  51.  
  52.     hMem=LocalAlloc(LPTR, CBOBJECT);
  53.  
  54.     if (NULL==hMem)
  55.         return FALSE;
  56.  
  57.     //All fields are initially NULL from the LocalAlloc.
  58.     pObj=(LPOBJECT)(PSTR)hMem;
  59.  
  60.     //Must set VTBL since we may pass this to an OLE function.
  61.     pObj->pvt=pDoc->pvt;
  62.  
  63.     //Set the previous and next pointers for this object in the list.
  64.     if (NULL==pDoc->pObjFirst)
  65.         pDoc->pObjFirst=pObj;
  66.  
  67.     pObj->pPrev=pDoc->pObjLast;
  68.  
  69.     if (NULL!=pObj->pPrev)
  70.         {
  71.         pObj->pNext=pObj->pPrev->pNext;
  72.         pObj->pPrev->pNext=pObj;
  73.         }
  74.     else
  75.         pObj->pNext=NULL;
  76.  
  77.     if (NULL!=pObj->pNext)
  78.         pObj->pNext->pPrev=pObj;
  79.  
  80.     pDoc->pObjLast=pObj;
  81.  
  82.     //Honor thy parent.
  83.     pObj->pDoc=pDoc;
  84.  
  85.     //We're all done!
  86.     pDoc->cObjects++;
  87.     *pfSuccess=TRUE;
  88.     return pObj;
  89.     }
  90.  
  91.  
  92.  
  93.  
  94. /*
  95.  * PObjectInitialize
  96.  *
  97.  * Purpose:
  98.  *  Initializes an OBJECT structure and assumes that the pObj field
  99.  *  in the structure already contains a valid OLEOBJECT pointer.
  100.  *
  101.  * Parameters:
  102.  *  pObj            LPOBJECT to the object to initialize.
  103.  *  pDoc            LPDOCUMENT to the owner of this object.
  104.  *
  105.  * Return Value:
  106.  *  LPOBJECT        pObj if successful, NULL otherwise.
  107.  */
  108.  
  109. LPOBJECT FAR PASCAL PObjectInitialize(LPOBJECT pObj, LPDOCUMENT pDoc)
  110.     {
  111.     WORD                wTemp;
  112.     LPSTR               pszT;
  113.     OLESTATUS           os;
  114.  
  115.     if (NULL==pObj || NULL==pDoc)
  116.         return NULL;
  117.  
  118.     //Add this object's name as an ATOM
  119.     wTemp=CBSCRATCH;
  120.     os=OleQueryName(pObj->pObj, pDoc->pszData1, &wTemp);
  121.  
  122.     if (OLE_OK!=os)
  123.         return NULL;
  124.  
  125.     if (0!=pObj->aName)
  126.         DeleteAtom(pObj->aName);
  127.  
  128.     pObj->aName=AddAtom(pDoc->pszData1);
  129.  
  130.     //Get the type, OT_LINK, OT_EMBEDDED, or OT_STATIC
  131.     os=OleQueryType(pObj->pObj, &pObj->dwType);
  132.  
  133.     if (OLE_OK!=os)
  134.         return NULL;
  135.  
  136.     /*
  137.      * Set these names with OLECLI only for an *embedded* object.  If
  138.      * you call this for a linked object you'll see OLE_ERROR_OBJECT.
  139.      */
  140.     if (OT_EMBEDDED==pObj->dwType)
  141.         {
  142.         //pDoc has the document name.
  143.         GetAtomName(pDoc->aCaption, pDoc->pszData2, CBSCRATCH);
  144.         os=OleSetHostNames(pObj->pObj, pDoc->pszData2, pDoc->pszData1);
  145.  
  146.         if (OLE_OK!=OsError(os, pDoc, pObj, TRUE))
  147.             return NULL;
  148.         }
  149.  
  150.     //Get the type of link, if we are indeed linked
  151.     if (OT_LINK==pObj->dwType)
  152.         {
  153.         os=OleGetLinkUpdateOptions(pObj->pObj, &pObj->dwLink);
  154.  
  155.         if (OLE_OK!=os)
  156.             return NULL;
  157.  
  158.         //If we're linked, get the linked document name.
  159.         if (FALSE==FObjectDataGet(pObj, pDoc->cfObjectLink, pDoc->pszData1))
  160.             return NULL;
  161.  
  162.         //Store the components of this linked item in ATOMS.
  163.         pszT=pDoc->pszData1;
  164.  
  165.         if (0!=pObj->aClass)
  166.             DeleteAtom(pObj->aClass);
  167.  
  168.         pObj->aClass=AddAtom(pszT);     //Classname
  169.  
  170.  
  171.         pszT+=lstrlen(pszT)+1;
  172.  
  173.         if (0!=pObj->aLink)
  174.             DeleteAtom(pObj->aLink);
  175.  
  176.         pObj->aLink=AddAtom(pszT);      //Link file
  177.  
  178.  
  179.         pszT+=lstrlen(pszT)+1;
  180.  
  181.         if (0!=pObj->aSel)
  182.             DeleteAtom(pObj->aSel);
  183.  
  184.         pObj->aSel=AddAtom(pszT);       //Selection
  185.         }
  186.  
  187.     return pObj;
  188.     }
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195. /*
  196.  * PObjectFree
  197.  *
  198.  * Purpose:
  199.  *  Frees all data in the OBJECT and frees the structure.
  200.  *
  201.  * Parameters:
  202.  *  pDoc            LPDOCUMENT containing first/last pointers that need
  203.  *                  to be managed.
  204.  *  pObj            LPOBJECT to the structure to free.
  205.  *
  206.  * Return Value:
  207.  *  LPOBJECT        NULL if the function succeeds, pObj otherwise
  208.  */
  209.  
  210. LPOBJECT FAR PASCAL PObjectFree(LPDOCUMENT pDoc, LPOBJECT pObj)
  211.     {
  212.     LPOBJECT        pPrev;
  213.     LPOBJECT        pNext;
  214.     OLESTATUS       os;
  215.  
  216.     if (NULL==pObj)
  217.         return NULL;
  218.  
  219.     if (NULL==LocalHandle((HANDLE)(DWORD)pObj))
  220.         return NULL;
  221.  
  222.     pPrev=pObj->pPrev;
  223.     pNext=pObj->pNext;
  224.  
  225.     if (NULL!=pObj->aSel)
  226.         DeleteAtom(pObj->aSel);
  227.  
  228.     if (NULL!=pObj->aLink)
  229.         DeleteAtom(pObj->aLink);
  230.  
  231.     if (NULL!=pObj->aClass)
  232.         DeleteAtom(pObj->aClass);
  233.  
  234.     if (NULL!=pObj->aName)
  235.         DeleteAtom(pObj->aName);
  236.  
  237.     //Free any cloned object we might be carrying.
  238.     if (NULL!=pObj->pObjUndo)
  239.         {
  240.         os=OleDelete(pObj->pObjUndo);
  241.  
  242.         pObj->pObj=pObj->pObjUndo;      //FOLEReleaseWait uses pObj->pObj
  243.         OsError(os, pDoc, pObj, TRUE);
  244.         }
  245.  
  246.     //Free the structure.
  247.     if (NULL!=LocalFree((HANDLE)(DWORD)pObj))
  248.         return pObj;
  249.  
  250.     //Remove this object from the list.
  251.     if (pDoc->pObjFirst==pObj)
  252.         pDoc->pObjFirst=pNext;
  253.  
  254.     if (pDoc->pObjLast==pObj)
  255.         pDoc->pObjLast=pPrev;
  256.  
  257.     if (NULL!=pPrev)
  258.         pPrev->pNext=pNext;
  259.  
  260.     if (NULL!=pNext)
  261.         pNext->pPrev=pPrev;
  262.  
  263.     pDoc->cObjects--;
  264.     return NULL;
  265.     }
  266.  
  267.  
  268.  
  269.  
  270. /*
  271.  * FObjectsEnumerate
  272.  *
  273.  * Purpose:
  274.  *  Enumerates all allocated OBJECT structures, passing them to
  275.  *  a specified enumeration function given in pfn which should appear
  276.  *  as:
  277.  *      BOOL FAR PASCAL EnumFunc(LPDOCUMENT pDoc, LPOBJECT pObj)
  278.  *
  279.  *  (EnumFunc can be any name).  The return value of EnumFunc is
  280.  *  TRUE to continue the enumeration, FALSE otherwise.
  281.  *
  282.  *  This function provides a different enumeration method than OleEnumObjects
  283.  *  since it contains the loop instead of embedding OleEnumObjects inside
  284.  *  your own loop.  The enumeration provided by this function is more
  285.  *  consistent with other Windows Enum* functions.
  286.  *
  287.  * Parameters:
  288.  *  pDoc            LPDOCUMENT identifying the owner of the objects.
  289.  *  pfn             LPFNOBJECTENUM to the enumeration handler.
  290.  *  dw              DWORD containing extra data to pass to the enumeration
  291.  *                  function.
  292.  *
  293.  * Return Value:
  294.  *  BOOL            TRUE if ALL objects were enumerated, FALSE if the
  295.  */
  296.  
  297. BOOL FAR PASCAL FObjectsEnumerate(LPDOCUMENT pDoc, LPFNOBJECTENUM pfn, DWORD dw)
  298.     {
  299.     LPOBJECT    pObj;
  300.  
  301.     pObj=pDoc->pObjFirst;
  302.  
  303.     /*
  304.      * Note:  If we didn't store a list of objects outselves, we could
  305.      * continually use OleEnumObjects.  However, OleEnumObjects only
  306.      * returns an LPOLEOBJECT and we would not have OUR OBJECT structure,
  307.      * meaning we'd have to look it up in our own list anyway.
  308.      */
  309.  
  310.     while (NULL!=pObj)
  311.         {
  312.         if (!(*pfn)(pDoc, pObj, dw))
  313.             break;
  314.  
  315.         pObj=pObj->pNext;
  316.         }
  317.  
  318.     return (NULL==pObj);
  319.     }
  320.  
  321.  
  322.  
  323.  
  324.  
  325. /*
  326.  * FObjectPaint
  327.  *
  328.  * Purpose:
  329.  *  Calls OleDraw for a specified object to draw the object ON THE SCREEN.
  330.  *  If the object is open, it also paints the newly drawn object with a
  331.  *  HS_BDIAGONAL hatch brush to show the open state.
  332.  *
  333.  * Parameters:
  334.  *  hDC             HDC on which to paint.
  335.  *  pRect           LPRECT giving area to paint.
  336.  *  pOLEObj         LPOLEOBJECT to the object to paint
  337.  *
  338.  * Return Value:
  339.  *  BOOL            TRUE if successful, FALSE otherwise.
  340.  */
  341.  
  342. BOOL FAR PASCAL FObjectPaint(HDC hDC, LPRECT pRect, LPOBJECT pObj)
  343.     {
  344.     OLESTATUS       os;
  345.     HBRUSH          hBr, hBrT;
  346.  
  347.     //Draw the object
  348.     os=OleDraw(pObj->pObj, hDC, pRect, NULL, NULL);
  349.     os=OsError(os, pObj->pDoc, pObj, TRUE);
  350.  
  351.     if (OLE_OK!=os)
  352.         return FALSE;
  353.  
  354.     //If this EMBEDDED object is open, patch a hatch over the image.
  355.     if (pObj->fOpen && OT_EMBEDDED==pObj->dwType)
  356.         {
  357.         hBr=CreateHatchBrush(HS_BDIAGONAL, GetSysColor(COLOR_HIGHLIGHT));
  358.         hBrT=SelectObject(hDC, hBr);
  359.  
  360.         /*
  361.          * The 0x00A000C9L ROP code does an AND between the pattern and
  362.          * the destination; there is no standard definition for this
  363.          * ROP code, but it's exactly what we want to draw COLOR_HIGHTLIGHT
  364.          * lines across the object when it's open.
  365.          */
  366.         PatBlt(hDC, pRect->left, pRect->top,
  367.                pRect->right-pRect->left, pRect->bottom-pRect->top, 0xA000C9L);
  368.  
  369.         SelectObject(hDC, hBrT);
  370.         DeleteObject(hBr);
  371.         }
  372.  
  373.     return TRUE;
  374.     }
  375.  
  376.  
  377.  
  378.  
  379.  
  380.  
  381.  
  382. /*
  383.  * FObjectRectSet
  384.  *
  385.  * Purpose:
  386.  *  Provides the object with a screen-relative rectangle.  The object
  387.  *  itself assumes that the rectangle contains coordinates in units defined
  388.  *  by the mapping mode in mm.  The rectangle given here is sent to the
  389.  *  OleSetBounds function for this object after which we call OleUpdate.
  390.  *
  391.  * Parameters:
  392.  *  pDoc            LPDOCUMENT containing OLE information.
  393.  *  pObj            LPOBEJCT to the object in which to store the handle.
  394.  *  pRect           LPRECT to the rectangle of the object in device units.
  395.  *  mm              WORD specifying the mapping mode of pRect.
  396.  *
  397.  * Return Value:
  398.  *  BOOL            TRUE the set succeeds, FALSE if OleSetBounds fails
  399.  *                  or if an invalid pointer is passed.
  400.  */
  401.  
  402. BOOL FAR PASCAL FObjectRectSet(LPDOCUMENT pDoc, LPOBJECT pObj, LPRECT pRect, WORD mm)
  403.     {
  404.     OLESTATUS       os;
  405.  
  406.     if (NULL==pObj || NULL==pRect)
  407.         return FALSE;
  408.  
  409.     RectConvertMappings(pRect, mm, MM_HIMETRIC);
  410.  
  411.     os=OleSetBounds(pObj->pObj, pRect);
  412.  
  413.     if (OLE_OK!=OsError(os, pDoc, pObj, TRUE))
  414.         return FALSE;
  415.  
  416.     os=OleUpdate(pObj->pObj);
  417.  
  418.     if (OLE_OK!=OsError(os, pDoc, pObj, TRUE))
  419.         return FALSE;
  420.  
  421.     return TRUE;
  422.     }
  423.  
  424.  
  425.  
  426.  
  427.  
  428.  
  429. /*
  430.  * FObjectRectGet
  431.  *
  432.  * Purpose:
  433.  *  Retrieves the object's rectangle stored in the specified units.
  434.  *
  435.  * Parameters:
  436.  *  pObj            LPOBJECT to the object concerned.
  437.  *  pRect           LPRECT
  438.  *  mm              WORD mapping mode in which to retrieve coordinates.
  439.  *
  440.  * Return Value:
  441.  *  BOOL            TRUE if the function succeeds, FALSE otherwise.
  442.  */
  443.  
  444. BOOL FAR PASCAL FObjectRectGet(LPOBJECT pObj, LPRECT pRect, WORD mm)
  445.     {
  446.     RECT            rc;
  447.     OLESTATUS       os;
  448.  
  449.     if (NULL==pObj || NULL==pRect)
  450.         return FALSE;
  451.  
  452.     os=OleQueryBounds(pObj->pObj, &rc);
  453.  
  454.     //The most common error here is usually OLE_ERROR_BLANK.
  455.     if (OLE_OK!=os)
  456.         return FALSE;
  457.  
  458.     RectConvertMappings(&rc, MM_HIMETRIC, mm);
  459.     CopyRect(pRect, &rc);
  460.     return TRUE;
  461.     }
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468. /*
  469.  * FObjectDataGet
  470.  *
  471.  * Purpose:
  472.  *  Calls OleGetData for a particular object to retrieve data
  473.  *  in the specified format, either ObjectLink or OwnerLink.
  474.  *  The contents are copied into a buffer pointed to by psz on which
  475.  *  no length assumptions are made.
  476.  *
  477.  * Parameters:
  478.  *  pObj            LPOBJECT containing the OLEOBJECT from which to
  479.  *                  retrieve data.
  480.  *  cf              WORD specifying the ObjectLink or OwnerLink format.
  481.  *  psz             LPSTR pointer to buffer to store the string.
  482.  *
  483.  * Return Value:
  484.  *  BOOL            TRUE if the function succeeds, FALSE otherwise.
  485.  */
  486.  
  487. BOOL FAR PASCAL FObjectDataGet(LPOBJECT pObj, WORD cf, LPSTR psz)
  488.     {
  489.     OLESTATUS       os;
  490.     HANDLE          hLink;
  491.     LPSTR           pszLink;
  492.     WORD            cch;
  493.  
  494.     if (NULL==pObj || NULL==psz)
  495.         return FALSE;
  496.  
  497.     //Get link data.
  498.     os=OleGetData(pObj->pObj, cf, &hLink);
  499.  
  500.     if (OLE_OK!=os && OLE_WARN_DELETE_DATA!=os)
  501.         return FALSE;
  502.  
  503.     pszLink=GlobalLock(hLink);
  504.  
  505.     //Copy the link data to the buffer.
  506.     if (NULL!=pszLink)
  507.         {
  508.         //Copy three separate null-terminated strings.
  509.         lstrcpy(psz, pszLink);
  510.         cch=lstrlen(pszLink)+1;
  511.  
  512.         lstrcpy(psz+cch, pszLink+cch);
  513.         cch+=lstrlen(pszLink+cch)+1;
  514.  
  515.         lstrcpy(psz+cch, pszLink+cch);
  516.  
  517.         //Add the final null-terminator.
  518.         cch+=lstrlen(pszLink+cch)+1;
  519.         *(psz+cch)=0;
  520.         }
  521.  
  522.     GlobalUnlock(hLink);
  523.  
  524.     if (OLE_WARN_DELETE_DATA==os)
  525.         GlobalFree(hLink);
  526.  
  527.     if (NULL==pszLink)
  528.         return FALSE;
  529.  
  530.     return TRUE;
  531.     }
  532.  
  533.  
  534.  
  535.  
  536.  
  537. /*
  538.  * FObjectDataSet
  539.  *
  540.  * Purpose:
  541.  *  Calls OleSetData for a particular object to update data in the
  542.  *  in the specified format, either ObjectLink or OwnerLink.  The only
  543.  *  changable field in the data is the document (2nd string) which
  544.  *  is provided in pszDoc.
  545.  *
  546.  *  FObjectDataSet passes the new data to OlsSetData and stores it
  547.  *  in psz; no assumptions are made about the length of psz.
  548.  *
  549.  * Parameters:
  550.  *  pDoc            LPDOCUMENT containing OLE information.
  551.  *  pObj            LPOBJECT containing the OLEOBJECT to receive the
  552.  *                  new data.
  553.  *  cf              WORD specifying the ObjectLink or OwnerLink format.
  554.  *  pszDoc          LPSTR to the new link file
  555.  *
  556.  *
  557.  * Return Value:
  558.  *  BOOL            TRUE if the function worked, FALSE otherwise.
  559.  *
  560.  */
  561.  
  562. BOOL FAR PASCAL FObjectDataSet(LPDOCUMENT pDoc, LPOBJECT pObj, WORD cf, LPSTR pszDoc)
  563.     {
  564.     HANDLE      hMem;
  565.     LPSTR       pszT;
  566.     OLESTATUS   os;
  567.  
  568.     if (NULL==pObj || NULL==pszDoc)
  569.         return FALSE;
  570.  
  571.     //OleSetData requires a global handle to the data.  Assume 1K is enough
  572.     hMem=GlobalAlloc(GHND | GMEM_DDESHARE, 1024);
  573.  
  574.     if (NULL==hMem)
  575.         return FALSE;
  576.  
  577.     pszT=GlobalLock(hMem);
  578.  
  579.     /*
  580.      * Copy the Object/OwnerLink formats.  Note that we similtaneously
  581.      * build the copy in psz and the new memory handle.
  582.      */
  583.  
  584.     //Copy the classname and point pszT to the document location.
  585.     pszT+=1+GetAtomName(pObj->aClass, pszT, 256);
  586.  
  587.     //Copy the new filename and point to the selection location.
  588.     if (NULL!=pObj->aLink)
  589.         DeleteAtom(pObj->aLink);
  590.  
  591.     pObj->aLink=AddAtom(pszDoc);
  592.     lstrcpy(pszT, pszDoc);
  593.     pszT+=lstrlen(pszT)+1;
  594.  
  595.     //Copy the old selection data.
  596.     pszT+=1+GetAtomName(pObj->aSel, pszT, 512);
  597.  
  598.     //Add the list terminator (second NULL)
  599.     *(pszT)=0;
  600.  
  601.     GlobalUnlock(hMem);
  602.  
  603.     //Update this data with OLE.
  604.     os=OleSetData(pObj->pObj, cf, hMem);
  605.  
  606.  
  607.     if (OLE_OK!=OsError(os, pDoc, pObj, TRUE))
  608.         return FALSE;
  609.  
  610.     return TRUE;
  611.     }
  612.  
  613.  
  614.  
  615.  
  616.  
  617. /*
  618.  * FOLEReleaseWait
  619.  *
  620.  * Purpose:
  621.  *  Enters a Peek/Translate/Dispatch message loop to process all messages
  622.  *  to the application until one or all objects are released.  This message
  623.  *  processing is necessary beacuse OLECLI.DLL and OLESVR.DLL communicate
  624.  *  with asynchronous DDE messages.
  625.  *
  626.  *  The fWaitForAll flag indicates how to interpret the pv parameter.
  627.  *
  628.  *      1.  If TRUE==fWaitForAll, then pv points to a CLIENT structure,
  629.  *          and we loop until cWait is zero.
  630.  *
  631.  *      2.  If FALSE==fWaitForAll, then pv points to an OLEOBJECT,
  632.  *          so loop until OleQueryReleaseStatus returns something
  633.  *          other than OLE_BUSY.
  634.  *
  635.  * Parameters:
  636.  *  fWaitForAll     BOOL indicating if pv is a CLIENT or OLEOBJECT,
  637.  *                  which defines how we terminate the loop.
  638.  *  pDoc            LPDOCUMENT containing OLE information, such as message
  639.  *                  procedures and the cWait counter.
  640.  *  pObj            LPOBJECT to the object to wait for if fWaitForAll is
  641.  *                  FALSE.  Ignored if fWaitForAll is TRUE.
  642.  *
  643.  * Return Value:
  644.  *  BOOL            TRUE if we yielded, FALSE otherwise. For what it's worth.
  645.  */
  646.  
  647. BOOL FAR PASCAL FOLEReleaseWait(BOOL fWaitForAll, LPDOCUMENT pDoc, LPOBJECT pObj)
  648.     {
  649.     BOOL        fRet=FALSE;
  650.     MSG         msg;
  651.  
  652.     while (TRUE)
  653.         {
  654.         //Test terminating condition.
  655.         if (fWaitForAll)
  656.             {
  657.             if (0==pDoc->cWait)
  658.                 break;
  659.             }
  660.         else
  661.             {
  662.             /*
  663.              * Depending on a flag change in the CallBack method is like
  664.              * handling an interrupt.  We could call OleQueryReleaseStatus
  665.              * as well for a polling technique.
  666.              */
  667.             if (pObj->fRelease)
  668.                 break;
  669.             }
  670.  
  671.  
  672.         /*
  673.          * We use PeekMessage here to make a point about power
  674.          * management and ROM Windows--GetMessage, when there's
  675.          * no more messages, will correctly let the system go into
  676.          * a low-power idle state.  PeekMessage by itself will not.
  677.          * If you do background processing in a PeekMessage loop like
  678.          * this, and there's no background processing to be done,
  679.          * then you MUST call WaitMessage to duplicate the idle
  680.          * state like GetMessage.
  681.          */
  682.  
  683.         if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
  684.             {
  685.             /*
  686.              * We will not see WM_QUIT in the middle of the application
  687.              * since this application MUST call PostQuitMessage to get
  688.              * in the queue.  Therefore we don't even worry about it.
  689.              */
  690.  
  691.             if (NULL!=pDoc->pfnMsgProc)
  692.                 (*pDoc->pfnMsgProc)(&msg);
  693.             }
  694.         else
  695.             {
  696.             /*
  697.              * If the application has some background processing
  698.              * to do, perform a piece of it here.  Otherwise make sure
  699.              * we somehow call WaitMessage to allow power-management
  700.              * functions to take effect.  You don't want to mess with
  701.              * battery life, now do you?
  702.              */
  703.  
  704.             if (NULL==pDoc->pfnBackProc)
  705.                 WaitMessage();
  706.             else
  707.                 {
  708.                 if (!(*pDoc->pfnBackProc)(&msg))
  709.                     WaitMessage();
  710.                 }
  711.  
  712.             fRet=TRUE;
  713.             }
  714.         }
  715.  
  716.     return fRet;
  717.     }
  718.  
  719.  
  720.  
  721.  
  722. /*
  723.  * OsError
  724.  *
  725.  * Purpose:
  726.  *  Provides a centralized error handler for OLE function calls, depending
  727.  *  on the value in os:
  728.  *
  729.  *      OLE_OK                  Return OLE_OK
  730.  *      OLE_BUSY                Display a message and return OLE_BUSY.
  731.  *      Any OLE error           Return that error.
  732.  *      OLE_WAIT_FOR_RELEASE    Call FOLEReleaseWait on the object if
  733.  *                              fWait is TRUE, then call OleQueryReleaseError
  734.  *                              for the return value.  Otherwise increment
  735.  *                              pDoc->cWait.
  736.  *
  737.  * Parameters:
  738.  *  os              OLESTATUS error value to check.
  739.  *  pDoc            LPDOCUMENT containing OLE information.
  740.  *  pObj            LPOBJECT containing the object that we manipulated.
  741.  *  fWait           BOOL indicates if we are to wait for release on the
  742.  *                  object or increment a flag for later waiting.
  743.  *
  744.  * Return Value:
  745.  *  OLESTATUS       New error code depending on the original os.
  746.  */
  747.  
  748. OLESTATUS FAR PASCAL OsError(OLESTATUS os, LPDOCUMENT pDoc, LPOBJECT pObj, BOOL fWait)
  749.     {
  750. #ifdef DEBUG
  751.     OLE_RELEASE_METHOD      orm;
  752.     char                    szMsg[128];
  753. #endif
  754.  
  755.     switch (os)
  756.         {
  757.         case OLE_OK:
  758.             break;
  759.  
  760.         case OLE_BUSY:
  761.             MessageBox(pDoc->hWnd, PSZOLE(IDS_OBJECTBUSY),
  762.                        PSZOLE(IDS_OLEERROR), MB_OK);
  763.             break;
  764.  
  765.         case OLE_WARN_DELETE_DATA:
  766.             break;
  767.  
  768.         case OLE_WAIT_FOR_RELEASE:
  769.             if (!fWait)
  770.                 {
  771.                 pDoc->cWait++;
  772.                 os=OLE_OK;
  773.                 break;
  774.                 }
  775.             else
  776.                 {
  777.                 pObj->fRelease=FALSE;
  778.                 FOLEReleaseWait(FALSE, pDoc, pObj);
  779.  
  780.                 os=OleQueryReleaseError(pObj->pObj);
  781.                 }
  782.  
  783.             if (OLE_OK==os)
  784.                 break;
  785.  
  786.             //FALL THROUGH if OLE_OK!=OleQueryReleaseError.
  787.  
  788.         //This is not a wonderful way to handle errors for end users.
  789.         default:
  790. #ifdef DEBUG
  791.             orm=OleQueryReleaseMethod(pObj->pObj);
  792.             wsprintf(szMsg, PSZOLE(IDS_OLEERRORMSG), orm, os);
  793.             OutputDebugString(szMsg);
  794.             OutputDebugString("\n\r");
  795. #endif
  796.             break;
  797.         }
  798.  
  799.     return os;
  800.     }
  801.